<template>
  <el-dialog
    v-model="visible"
    title="F-V 判据自动识别图"
    width="70%"
    :close-on-click-modal="false"
    :destroy-on-close="true"
  >
    <div class="dialog-content">
      <div class="controls">
        <el-button type="primary" @click="generateData">加载数据</el-button>
        <el-button @click="runDetection">运行识别</el-button>
        <el-button @click="exportCSV">导出 CSV</el-button>

        <el-form :inline="true" class="params-form">
          <el-form-item label="样本点数">
            <el-input-number v-model="params.n" :min="50" :max="5000" />
          </el-form-item>
          <el-form-item label="噪声强度">
            <el-input-number v-model="params.noise" :min="0" :max="5" step="0.1" />
          </el-form-item>
          <el-form-item label="加速开始时间 (s)">
            <el-input-number v-model="params.t0" :min="0" :max="10000" />
          </el-form-item>
        </el-form>
      </div>

      <div class="charts">
        <div ref="timeChart" class="chart time-chart"></div>
        <div ref="fvChart" class="chart fv-chart"></div>
      </div>

      <div class="legend">
        <span class="leg stable">● 稳定</span>
        <span class="leg prec">● 预警</span>
        <span class="leg accel">● 加速</span>
      </div>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="close">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
/**
 * F-V 判据自动识别（基于速度-加速度关系）
 * - 生成合成位移数据（noise + 指数加速段）
 * - 计算速度与加速度（有限差分）
 * - 绘制时间序列与 F-V 散点图 (echarts)
 * - 简单自动识别：基于速度阈与加速度正值、以及速度趋势判定阶段
 *
 * 说明：识别逻辑为可解释的统计阈值实现，便于联调与替换为更复杂算法（如 log-log 拟合、临界变点检测等）
 */

import { ref, onMounted, watch, nextTick } from "vue";
import * as echarts from "echarts";
import { ElMessage } from "element-plus";

// 可见性
const visible = ref(false);
const open = () => (visible.value = true);
const close = () => (visible.value = false);
defineExpose({ open, close });

// refs for charts
const timeChart = ref<HTMLDivElement | null>(null);
const fvChart = ref<HTMLDivElement | null>(null);
let timeChartInstance: echarts.ECharts | null = null;
let fvChartInstance: echarts.ECharts | null = null;

// 参数（可由用户调整）
const params = ref({
  n: 500,
  noise: 0.5,
  t0: 300, // 加速开始的时间点（秒）——在合成数据中使用
});

// 数据容器
type DataPoint = { t: number; disp: number; vel: number | null; acc: number | null; stage?: string };
const data = ref<DataPoint[]>([]);

// 生成合成数据：基线噪声 + 从 t0 开始的指数加速位移
function generateSyntheticData(n: number, noise: number, t0: number) {
  const dt = 1; // 固定采样间隔 1s，简化处理
  const arr: DataPoint[] = [];
  // parameters for synthetic ramp
  const baselineAmp = 0.05;
  const accelAmp = 0.001;
  const growthRate = 0.02; // 指数增长速率（影响加速度强度）
  for (let i = 0; i < n; i++) {
    const t = i * dt;
    // base slow motion (small linear drift)
    let disp = baselineAmp * Math.sin(0.01 * t) + 0.0001 * t;
    // if after t0, add an exponential ramp
    if (t >= t0) {
      const tau = t - t0;
      disp += accelAmp * Math.exp(growthRate * tau) - accelAmp; // keep continuous
    }
    // add gaussian-like noise (simple)
    disp += (Math.random() - 0.5) * noise;
    arr.push({ t, disp, vel: null, acc: null });
  }
  // compute velocity & acceleration by finite differences
  for (let i = 0; i < arr.length; i++) {
    if (i === 0) {
      arr[i].vel = 0;
      arr[i].acc = 0;
    } else {
      const dt_local = arr[i].t - arr[i - 1].t;
      const vel = (arr[i].disp - arr[i - 1].disp) / dt_local;
      arr[i].vel = vel;
      if (i === 1) {
        arr[i].acc = 0;
      } else {
        const velPrev = arr[i - 1].vel!;
        arr[i].acc = (vel - velPrev) / dt_local;
      }
    }
  }
  return arr;
}

// 识别规则（简单可调）
// - 计算速度均值与标准差，速度超过 mean + k*std 且加速度 > 0 视为“加速”
// - 速度在 mean + m*std 与 mean + k*std 之间并且加速度呈上升趋势视为“预警”
// - 其他视为“稳定”
function detectStages(arr: DataPoint[]) {
  const velocities = arr.map((d) => d.vel ?? 0);
  const mean = velocities.reduce((s, v) => s + v, 0) / velocities.length;
  const variance = velocities.reduce((s, v) => s + (v - mean) ** 2, 0) / velocities.length;
  const std = Math.sqrt(variance);

  const k = 2.5; // 加速阈系数
  const m = 1.0; // 预警阈系数

  // 速度线性趋势窗口（判断是否有上升趋势）
  const trendWindow = 10;

  for (let i = 0; i < arr.length; i++) {
    const v = arr[i].vel ?? 0;
    const a = arr[i].acc ?? 0;

    // compute local velocity trend (slope over last trendWindow points)
    let trend = 0;
    if (i >= trendWindow) {
      const t0 = arr[i - trendWindow].t;
      const t1 = arr[i].t;
      const v0 = arr[i - trendWindow].vel ?? 0;
      const v1 = v;
      trend = (v1 - v0) / (t1 - t0 + 1e-9);
    }

    if (v > mean + k * std && a > 0) {
      arr[i].stage = "加速";
    } else if (v > mean + m * std && trend > 0 && a >= 0) {
      arr[i].stage = "预警";
    } else {
      arr[i].stage = "稳定";
    }
  }
  return arr;
}

// chart update helpers
function initCharts() {
  if (timeChart.value) {
    timeChartInstance = echarts.init(timeChart.value);
  }
  if (fvChart.value) {
    fvChartInstance = echarts.init(fvChart.value);
  }
  // resize on dialog show
  setTimeout(() => {
    timeChartInstance?.resize();
    fvChartInstance?.resize();
  }, 300);
}

function updateCharts() {
  if (!timeChartInstance || !fvChartInstance) return;
  const t = data.value.map((d) => d.t);
  const disp = data.value.map((d) => d.disp);
  const vel = data.value.map((d) => d.vel ?? 0);
  const acc = data.value.map((d) => d.acc ?? 0);

  // time series chart: displacement / velocity / acceleration
  const timeOption: echarts.EChartsOption = {
    tooltip: { trigger: "axis" },
    legend: { data: ["位移", "速度", "加速度"] },
    grid: { left: "6%", right: "6%", bottom: "8%", top: "10%" },
    xAxis: { type: "category", data: t, name: "t(s)" },
    yAxis: [{ type: "value", name: "位移" }, { type: "value", name: "速/加" }],
    series: [
      { name: "位移", type: "line", data: disp, yAxisIndex: 0, smooth: true },
      { name: "速度", type: "line", data: vel, yAxisIndex: 1 },
      { name: "加速度", type: "line", data: acc, yAxisIndex: 1 },
    ],
  };
  timeChartInstance.setOption(timeOption);

  // F-V scatter with color by stage
  const pointsStable: [number, number][] = [];
  const pointsPrec: [number, number][] = [];
  const pointsAccel: [number, number][] = [];
  for (const d of data.value) {
    const vx = d.vel ?? 0;
    const ay = d.acc ?? 0;
    if (d.stage === "加速") pointsAccel.push([vx, ay]);
    else if (d.stage === "预警") pointsPrec.push([vx, ay]);
    else pointsStable.push([vx, ay]);
  }

  const fvOption: echarts.EChartsOption = {
    tooltip: {
      trigger: "item",
      formatter: function (params: any) {
        const idx = params.dataIndex;
        return `速度: ${params.data[0].toFixed(5)}<br/>加速度: ${params.data[1].toFixed(6)}`;
      },
    },
    xAxis: { name: "速度 (单位/s)", scale: true },
    yAxis: { name: "加速度 (单位/s²)", scale: true },
    series: [
      { name: "稳定", type: "scatter", data: pointsStable, symbolSize: 6 },
      { name: "预警", type: "scatter", data: pointsPrec, symbolSize: 6 },
      { name: "加速", type: "scatter", data: pointsAccel, symbolSize: 6 },
    ],
  };
  fvChartInstance.setOption(fvOption);
}

// 运行识别并更新图
function runDetection() {
  if (data.value.length === 0) {
    ElMessage.warning("请先生成或导入数据！");
    return;
  }
  detectStages(data.value);
  updateCharts();
  ElMessage.success("识别完成（基于速度/加速度统计阈值）");
}

// 导出 CSV（时间, 位移, 速度, 加速度, 阶段）
function exportCSV() {
  if (data.value.length === 0) {
    ElMessage.warning("无数据可导出");
    return;
  }
  const header = ["t", "disp", "vel", "acc", "stage"];
  const rows = data.value.map((d) => `${d.t},${d.disp},${d.vel ?? ""},${d.acc ?? ""},${d.stage ?? ""}`);
  const csv = [header.join(","), ...rows].join("\n");
  const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `fv_data_${Date.now()}.csv`;
  a.click();
  URL.revokeObjectURL(url);
}

// 生成假数据并即时绘图（并运行识别）
function generateData() {
  data.value = generateSyntheticData(params.value.n, params.value.noise, params.value.t0);
  detectStages(data.value);
  nextTick(() => updateCharts());
  ElMessage.success("已生成假数据并更新图表");
}

// 初始化图表（在 dialog 打开时创建）
watch(visible, (v) => {
  if (v) {
    nextTick(() => {
      initCharts();
      // 如果没有数据，先生成一组默认数据
      if (data.value.length === 0) {
        generateData();
      } else {
        updateCharts();
      }
    });
  } else {
    // 销毁图表实例避免内存泄露
    setTimeout(() => {
      timeChartInstance?.dispose();
      fvChartInstance?.dispose();
      timeChartInstance = null;
      fvChartInstance = null;
    }, 200);
  }
});

// 挂载时初始化容器（若组件已打开则在 watch 里执行）
onMounted(() => {
  // nothing here; chart init occurs on visible=true
});
</script>

<style scoped>
.dialog-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 8px 12px;
}
.controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.params-form {
  margin-left: 12px;
}
.charts {
  display: flex;
  gap: 12px;
  height: 420px;
}
.chart {
  flex: 1;
  border: 1px solid #eef2f6;
  border-radius: 6px;
}
.time-chart {
  min-width: 50%;
}
.fv-chart {
  min-width: 45%;
}
.legend {
  display: flex;
  gap: 14px;
  align-items: center;
  margin-top: 6px;
}
.legend .leg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
}
.legend .stable { color: #6b9ef8; }
.legend .prec { color: #ffb74d; }
.legend .accel { color: #ff6b6b; }
</style>
